package com.liuceng.zen.web.controller;

import com.alibaba.fastjson.JSONArray;
import com.liuceng.zen.Page;
import com.liuceng.zen.constants.Constants;
import com.liuceng.zen.mapper.AdDirectedMapper;
import com.liuceng.zen.pojo.domain.*;
import com.liuceng.zen.pojo.form.AdForm;
import com.liuceng.zen.pojo.form.FrontAdGroupForm;
import com.liuceng.zen.service.*;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 
 * @author
 *
 */
@Controller
public class AdController extends BaseController {
  @Autowired
  MemberDepartmentRelKeyService memberDepartmentRelKeyService;
  @Autowired
  MessageService messageService;
  @Autowired
  NewRptFrontAdGroupDailyService newRptFrontAdGroupDailyService;
  @Autowired
  private MemberService memberService;
  @Autowired
  private GdtAdGroupService gdtAdGroupService;
  @Autowired
  private DictRegionService dictRegionService;
  @Autowired
  private RptFrontAdGroupService rptFrontAdGroupService;
  @Autowired
  private DashboardService dashboardService;
  @Autowired
  private FrontAdGroupService frontAdGroupService;
  @Autowired
  private FrontCampaignService frontCampaignService;
  @Autowired
  private LandingPageService landingPageService;
  @Autowired
  private AdDirectedMapper adDirectedMapper;
  @Autowired
  private GroupNotThroughReasonService groupNotThroughReasonService;
  @Autowired
  private FrontSelfOperateCreativeService frontSelfOperateCreativeService;
  @Autowired
  private CrtSizeMediumMenuService crtSizeMediumMenuService;
  @Value("${hailiangtong.url}")
  private String hailiangtong;

  // 广告和计划---广告---广告管理
  @RequestMapping(value = "/ads", method = RequestMethod.GET)
  public String index(@ModelAttribute("form") AdForm form) {
    Integer memberId = getCurrentUserId();
    Member member = memberService.find(memberId);
    member.setCityStr(dictRegionService.find(member.getCity()).getName());
    // 查询分组后的adgrouplandingPageService
    List<GdtAdGroup> adgroups = gdtAdGroupService.findFrontAdGroups(memberId);
    // 获取前台广告集合
    List<RptFrontAdGroup> fAdGroups = rptFrontAdGroupService.convert2FrontAdGroup(member, adgroups);
    //
    form.setAds(fAdGroups);
    return "ad/index";
  }

  @RequestMapping(value = "/ads/detail", method = RequestMethod.GET)
  public String detail(@ModelAttribute("form") AdForm form) {
    Integer memberId = getCurrentUserId();
    Member member = memberService.find(memberId);
    member.setCityStr(dictRegionService.find(member.getCity()).getName());
    // 按广告创意规格查询广告adgroup
    List<GdtAdGroup> adgroups =
        gdtAdGroupService.findFrontAdGroupByCrtSize(memberId, form.getCrtSize());
    List<RptFrontAdGroup> fAdGroups = rptFrontAdGroupService.convert2FrontAdGroup(member, adgroups);
    form.setAds(fAdGroups);
    return "ad/detail";
  }

  @RequestMapping(value = "/ajax/crtSize/detail", method = RequestMethod.GET)
  public String detailData(@ModelAttribute("form") AdForm form, HttpServletRequest req) {
    // 昨天、过去七天、过去三十天，ajax请求获取数据
    final String YESTERDAY = "1";
    final String LAST_7_DAYS = "2";
    final String LAST_30_DAYS = "3";
    //
    String timeType =
        req.getParameter("timeType") == null ? YESTERDAY : req.getParameter("timeType").toString();
    String crtSize = req.getParameter("crtSize");

    String start = req.getParameter("start");
    String end = req.getParameter("end");
    SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd");
    // 判断是移动端还是PC端
    // 昨天时间
    Date endDate = new Date();
    Date startDate = endDate;
    try {
      endDate = simple.parse(end);
      startDate = simple.parse(start);
    } catch (ParseException e) {
      logger.debug(e.getMessage());
      logger.error(e.getMessage() + "  时间转化异常", e);
    }
    // 查询条件
    Map<String, Object> params = new HashMap<>();
    params.put("startDate", DateFormatUtils.format(startDate, "yyyy-MM-dd"));
    params.put("endDate", DateFormatUtils.format(endDate, "yyyy-MM-dd"));
    params.put("memberId", getCurrentUserId());
    params.put("crtSize", Integer.parseInt(crtSize));
    // / 获取当前账号下pc或移动的广告计划总花费，总曝光量，总点击量
    Map<String, Object> totalData = dashboardService.findTotalDataByAdGroup(params);
    // 获取当前账号下某一时间段的广告计划总花费，总曝光量，总点击量
    List<Map<String, Object>> data = dashboardService.findDataListByAdGorup(params);
    // 批量处理点击率
    data =
        data.stream()
            .map(
                d -> {
                  d.put(
                      "ctr",
                      d.get("pv") == null || 0 == Integer.parseInt(d.get("pv").toString()) ? new BigDecimal(
                          0) : new BigDecimal(100 * Integer.parseInt(d.get("pc").toString())
                          / Integer.parseInt(d.get("pv").toString())));
                  return d;
                }).collect(Collectors.toList());
    //
    form.setTotalData(totalData);
    form.setDataList(data);
    form.setData(data.stream().map(d -> {
      return JSONArray.toJSON(d);
    }).collect(Collectors.toList()));
    form.setTimeSelect(timeType);
    form.setStart(start);
    form.setEnd(end);
    return "ad/_detail";
  }

  // 广告列表
  @RequestMapping(value = "/ads/list", method = RequestMethod.GET)
  public String list(@ModelAttribute("form") FrontAdGroupForm form) {
    form.setMemberId(getCurrentUserId());
    form.setPage(frontAdGroupService.findPage(form));
    // 设置广告计划
    Map<String, Object> maps = new HashMap<>();
    maps.put("memberId", getCurrentUserId());
    List<FrontCampaign> lists = frontCampaignService.findByMemberId(maps);
    form.setFrontCampaigns(lists);
    Page<FrontAdGroup> page = frontAdGroupService.findPage(form);
    List<Map<String, Object>> memberFrontAdGroup = new ArrayList();
    List<FrontAdGroup> list = page.getContent();

    if (list != null && list.size() > 0) {
      for (int i = 0; i < list.size(); i++) {
        Map<String, Object> map = new HashMap<>();
        map.put("frontAdGroupId", list.get(i).getId());
        map.put("auditType", BaseDomain.AUDIT_PASS);
        NewRptFrontAdGroupDaily newRptFrontAdGroupDaily =
            newRptFrontAdGroupDailyService.findRptAdGroupByAdGroupId(map);

        //只有正在投放中的广告是需要从队列中获取广告出价和广告最低出价的
        if(list.get(i).getFrontAdGroupType()==2){
          BigDecimal adOffer = frontAdGroupService.getAdOffer(list.get(i).getId(),list.get(i));
          list.get(i).setAdOffer(adOffer);
          BigDecimal minAdOffer = frontAdGroupService.getMinAdOffer(list.get(i).getFrontCampaignType(),getUserContext().getMember());
          map.put("minAdOffer",minAdOffer);
        }

        // 曝光量
        Integer viewNum =
            newRptFrontAdGroupDaily == null ? 0 : newRptFrontAdGroupDaily.getViewNum();
        // 点击数
        Integer clickNum =
            newRptFrontAdGroupDaily == null ? 0 : newRptFrontAdGroupDaily.getClickNum();
        // 花费
        BigDecimal cost =
            newRptFrontAdGroupDaily == null ? new BigDecimal(0) : newRptFrontAdGroupDaily.getCost();
        map.put("ctr", viewNum == 0 ? new BigDecimal(0)
            : new BigDecimal(clickNum * 100.0 / viewNum));
        map.put(
            "costPerClick",
            clickNum == 0 ? new BigDecimal(0) : cost.divide(new BigDecimal(clickNum), 3,
                RoundingMode.UP));
        map.put("frontAdGroup", list.get(i));
        map.put("viewNum", viewNum);
        map.put("clickNum", clickNum);
        map.put("cost", cost);
        map.put("newRptFrontAdGroupDaily", newRptFrontAdGroupDaily);
        memberFrontAdGroup.add(map);
      }
    }
    form.setMemberFrontAdGourp(memberFrontAdGroup);
    // 已经创建的广告数量
    form.setAdCount(frontAdGroupService.selectAdGroupCount(getCurrentUserId()));
    if (getUserContext().getMember().getOperationType() == 2) {
      return "ad/list";
    } else {
      return "ad/old_list";
    }
  }

  // 查询广告审核不通过的原因
  @RequestMapping(value = "/ads/audit/reason/{id}", method = RequestMethod.GET)
  @ResponseBody
  public String getReason(@PathVariable Integer id) {
    GroupNotThroughReason reason = groupNotThroughReasonService.getResultOne(id);
    return reason.getReason();
  }

  // 操作正在投放的广告变成暂停状态或者由暂停变成开始投放
  @RequestMapping(value = "/ads/suspend_or_start/{id}", method = RequestMethod.POST)
  @ResponseBody
  public String suspended(@PathVariable Integer id) {
    frontAdGroupService.changeAdGroupType(id,getCurrentUserId(),getUserContext().getMember());
    frontAdGroupService.processAdGroupPutLife(frontAdGroupService.find(id));
    return "success";
  }

  // 添加广告页面
  @RequestMapping(value = "/ads/add", method = RequestMethod.GET)
  public String add(@ModelAttribute("form") FrontAdGroupForm form) {
    long starTime=System.currentTimeMillis();

    Map<String, Object> map = new HashMap<>();
    map.put("memberId", getCurrentUserId());

    //1 获取计划
    List<FrontCampaign> list = frontCampaignService.findByMemberId(map);

    //2 查询该客户的落地页
    map.put("showType", LandingPage.SHOW_TYPE);
    map.put("status", LandingPage.STATUS);
    List<LandingPage> landingPages = landingPageService.search(map);
    form.setLandingPages(landingPages);

//    if (list.size() > 0) {
//      for (FrontCampaign campaign:list) {
//        if (1 == campaign.getCampaignType()) {
//          form.setPcDayBudget(null == campaign.getDayBudget() ? new BigDecimal("0") : campaign.getDayBudget());
//          form.setPcAdOffer(null == campaign.getAdOffer() ? new BigDecimal("0") : campaign.getAdOffer());
//        } else if (2 == campaign.getCampaignType()) {
//          form.setMobileDayBudget(null == campaign.getDayBudget() ? new BigDecimal("0") : campaign.getDayBudget());
//          form.setMobileAdOffer(null == campaign.getAdOffer() ? new BigDecimal("0") : campaign.getAdOffer());
//        }
//      }
//    }
    //3 获取广告的pc和移动端最低出价
    BigDecimal pcMinAdOffer = frontAdGroupService.getMinAdOffer(1,getUserContext().getMember());
    form.setPcMinAdOffer(pcMinAdOffer);
    BigDecimal mobileMinAdOffer = frontAdGroupService.getMinAdOffer(2,getUserContext().getMember());
    form.setMobileMinAdOffer(mobileMinAdOffer);

    form.setFrontCampaigns(list);
    //4 获取建议出价信息
    form.setMobileOfferMessage(frontAdGroupService.getMobileOfferMessage());
    form.setPcOfferMessage(frontAdGroupService.getPcOfferMessage());
    //5 判断是否能够创建PC端广告
    List<FrontSelfOperateCreative> pcList = frontSelfOperateCreativeService.checkPcAndMobile(getCurrentUserId(),1);
    if(pcList!=null&&pcList.size()>0){
      form.setPcIsCreated(true);
    }else{
      List<CrtSizeMediumMenu> pcCrtSizeList = crtSizeMediumMenuService.findSomeByType(getCurrentUserId(),1);
      if(pcCrtSizeList!=null&&pcCrtSizeList.size()>0){
        form.setPcIsCreated(true);
      }else{
        form.setPcIsCreated(false);
      }
    }
    //6 判断是否能够创建移动端广告
    List<FrontSelfOperateCreative> mobileList = frontSelfOperateCreativeService.checkPcAndMobile(getCurrentUserId(),2);
    if(mobileList!=null&&mobileList.size()>0){
      form.setMobileIsCreated(true);
    }else{
      List<CrtSizeMediumMenu> mobileCrtSizeList = crtSizeMediumMenuService.findSomeByType(getCurrentUserId(),2);
      if(mobileCrtSizeList!=null&&mobileCrtSizeList.size()>0){
        form.setMobileIsCreated(true);
      }else{
        form.setMobileIsCreated(false);
      }
    }
    long endTime=System.currentTimeMillis();
    logger.info("获取广告添加页面的时间为："+(endTime-starTime));
    return "ad/add";
  }

  // 添加广告
  @RequestMapping(value = "/ads/add", method = RequestMethod.POST)
  @ResponseBody
  public String doAdd(@ModelAttribute("form") FrontAdGroupForm form, RedirectAttributes redirectAttributes) {
    long starTime=System.currentTimeMillis();
    //保存广告、定向、创意
    frontAdGroupService.addFrontAdGroup(form,getCurrentUserId(),getUserContext().getMember());
    redirectAttributes.addFlashAttribute(Constants.OK_MSG, "广告添加成功");
    long endTime=System.currentTimeMillis();
    logger.info("广告添加的时间为："+(endTime-starTime));
    return "success";
  }

  // 删除广告
  @RequestMapping(value = "/ads/delete/{id}", method = RequestMethod.POST)
  public @ResponseBody String delete(@PathVariable Integer id) {
    long starTime=System.currentTimeMillis();
    frontAdGroupService.deleteFrontAdGroup(id,hailiangtong,getUserContext().getMember());
    long endTime=System.currentTimeMillis();
    logger.info("广告删除的时间为："+(endTime-starTime));
    return "success";
  }

  // 修改广告
  @RequestMapping(value = "/ads/edit", method = RequestMethod.GET)
  public String edit(@ModelAttribute("form") FrontAdGroupForm form, Integer frontAdGroupId) {
    long starTime=System.currentTimeMillis();
    //1 获取计划
    Map<String, Object> map = new HashMap<>();
    map.put("memberId", getCurrentUserId());
    List<FrontCampaign> list = frontCampaignService.findByMemberId(map);
    form.setFrontCampaigns(list);

    //2 获取广告的pc和移动端最低出价
    BigDecimal pcMinAdOffer = frontAdGroupService.getMinAdOffer(1,getUserContext().getMember());
    form.setPcMinAdOffer(pcMinAdOffer);
    BigDecimal mobileMinAdOffer = frontAdGroupService.getMinAdOffer(2,getUserContext().getMember());
    form.setMobileMinAdOffer(mobileMinAdOffer);

    //3 落地页
    map.put("showType", LandingPage.SHOW_TYPE);
    map.put("status", LandingPage.STATUS);
    List<LandingPage> landingPages = landingPageService.search(map);
    form.setLandingPages(landingPages);

    //4 获取建议出价信息
    form.setMobileOfferMessage(frontAdGroupService.getMobileOfferMessage());
    form.setPcOfferMessage(frontAdGroupService.getPcOfferMessage());

    //5 查询与该广告绑定的所有定向
    map.put("frontAdGroupId", frontAdGroupId);
    List<AdDirected> adDirecteds = adDirectedMapper.selectAdDirected(map);
    if (adDirecteds.size() > 0 && adDirecteds != null) {
      for (AdDirected adDirected:adDirecteds) {
        if (adDirected.getAdTargetMarketType() == 2) {
          String[] area = adDirected.getAdTargetMarketArea().split(",");
          if (area.length > 0 && area != null) {
            String names = dictRegionService.findListNameByIds(area);
            adDirected.setAdTargetMarketArea(names);
          }
        }
      }
    }
    form.setAdDirecteds(adDirecteds);

    //6 获取广告
    FrontAdGroup frontAdGroup = frontAdGroupService.find(frontAdGroupId);
    form.setFrontAdGroup(frontAdGroup);
    //7 获取广告投放时间
    if (frontAdGroup != null && frontAdGroup.getAdPutType() == 2) {
      SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd");
      form.setAdPutStartAt(simple.format(frontAdGroup.getAdPutStartAt()));
      form.setAdPutEndAt(simple.format(frontAdGroup.getAdPutEndAt()));
    }
    //8 获取自运营广告创意
    List<FrontSelfOperateCreative> creatives = frontSelfOperateCreativeService.search(map);
    form.setFrontSelfOperateCreatives(creatives);
    long endTime=System.currentTimeMillis();
    logger.info("获取广告编辑页面的时间为："+(endTime-starTime));
    return "ad/edit";
  }

  // 修改广告
  @RequestMapping(value = "/ads/edit/{id}", method = RequestMethod.POST)
  @ResponseBody
  public String doEdit(@PathVariable Integer id, @ModelAttribute("form") FrontAdGroupForm form) {
    long starTime=System.currentTimeMillis();
    frontAdGroupService.editFrontAdGroup(form,id,getUserContext().getMember(),hailiangtong);
    //处理广告投放生命时长
    frontAdGroupService.processAdGroupPutLife(frontAdGroupService.find(id));
    long endTime=System.currentTimeMillis();
    logger.info("广告编辑的时间为："+(endTime-starTime));
    return "success";
  }

  @RequestMapping(value = "/ads/check_citys", method = RequestMethod.GET)
  public @ResponseBody Object checkCitys() {
    List<DictRegion> provinces = dictRegionService.findProvinces();
    List<DictRegion> citys = provinces.stream().map(p -> {
      List<DictRegion> list = dictRegionService.findRegions(2, p.getId());
      for (DictRegion one : list) {
        p.getChildren().add(one);
      }
      return p;
    }).collect(Collectors.toList());

    return citys;
  }

  // @RequestMapping(value = "/common/area/{level}/{id}", method =
  // RequestMethod.GET)
  // public @ResponseBody List<DictRegion> getRegions(@PathVariable Integer
  // level,
  // @PathVariable Integer id) {
  // List<DictRegion> regions = dictRegionService.findRegions(level, id);
  // return regions;
  // }
}
